Skip to content

wolfTPM SPDM support (Nuvoton NPCT75x and NSING NS350)#458

Merged
dgarske merged 11 commits intowolfSSL:masterfrom
aidangarske:add-full-spdm-support
Apr 7, 2026
Merged

wolfTPM SPDM support (Nuvoton NPCT75x and NSING NS350)#458
dgarske merged 11 commits intowolfSSL:masterfrom
aidangarske:add-full-spdm-support

Conversation

@aidangarske
Copy link
Copy Markdown
Member

@aidangarske aidangarske commented Feb 20, 2026

Description

Migrates the standalone wolfSPDM library into wolfTPM as an in-tree spdm/
subdirectory and adds full SPDM support for both Nuvoton NPCT75x and
Nations NS350 TPMs. Eliminates the external dependency a single
--enable-spdm configure flag builds everything.

wolfSPDM Library (spdm/)

  • SPDM 1.3 (DSP0274) with Algorithm Set B (P-384, SHA-384, AES-256-GCM, HKDF)
  • Standard mode: works with libspdm spdm-emu responder for testing
  • TCG SPDM Binding: vendor-defined commands (GET_PUBK, GIVE_PUB, SPDMONLY,
    GET_STS_, TPM2_CMD, PSK_SET_, PSK_CLR_)
  • Identity key session: GET_VERSION, GET_CAPABILITIES, NEGOTIATE_ALGORITHMS,
    GET_PUBK, KEY_EXCHANGE, GIVE_PUB, FINISH
  • PSK session: GET_VERSION, GET_CAPABILITIES, NEGOTIATE_ALGORITHMS,
    PSK_EXCHANGE, PSK_FINISH
  • Secured messaging: AES-256-GCM AEAD with sequence number tracking
  • Static memory mode (zero-malloc) and dynamic mode (--enable-spdm-dynamic-mem)
  • Unit test suite (spdm/test/unit_test.c)

Nuvoton NPCT75x Support

  • NTC2_PreConfig vendor commands for SPDM enable/disable
  • SPDM-only mode: lock/unlock enforcement over identity key sessions
  • Auto-SPDM: transparent session establishment when TPM is in SPDM-only mode
  • Tested: 6/6 hardware tests (status, connect, lock, unit test, unlock, caps)

Nations NS350 Support

PSK Mode

  • PSK_SET/PSK_CLEAR vendor commands with 32-byte ClearAuth (TCG PC Client spec)
  • PSK_EXCHANGE/PSK_FINISH session establishment (Salt_0 = 0xFF for PSK mode)
  • GET_STATUS with response parsing (PSKSet, SPDMOnly, spec version)
  • SPDM_ONLY lock/unlock for PSK mode
  • Tested: 10/10 PSK lifecycle tests (provision, connect, clear, re-provision)

Identity Key Mode

  • Shared TCG SPDM binding protocol with Nuvoton
  • TPM2_VendorSpdmIdentityKeySet for identity key provisioning
  • TODO: Re-test on firmware 0.1.0.15 (digest changed to SHA-384(TPMT_PUBLIC))

wolfTPM Integration

  • 13+ new wolfTPM2_Spdm*() wrapper API functions in tpm2_wrap.h
  • Transparent SPDM transport in TPM2_SendCommand() — all TPM commands
    automatically encrypted when SPDM session is active
  • TIS I/O callback for routing SPDM through SPI/I2C TPM FIFO
  • Auto-generated ephemeral P-384 key pair for mutual authentication

SPDM Demo (examples/spdm/)

  • spdm_demo.c: Nuvoton and Nations hardware modes
  • spdm_test.sh: Automated tests for nuvoton, nations, and nations-psk modes

TCG SPDM Vendor Commands

VdCode Command Nuvoton Nations
GET_PUBK Get Public Key Yes Yes
GIVE_PUB Give Public Key Yes Yes
TPM2_CMD TPM Command Yes Yes
GET_STS_ Get Status Yes Yes
SPDMONLY SPDM-Only Mode Yes Yes
PSK_SET_ PSK Set N/A Yes
PSK_CLR_ PSK Clear N/A Yes

Test Plan

  • Build with --enable-spdm --enable-nuvoton
  • Build with --enable-spdm --enable-nations
  • Build without --enable-spdm (no breakage)
  • 26/26 unit tests PASS
  • 6/6 Nuvoton hardware tests PASS
  • 10/12 Nations PSK hardware tests PASS. (two still need testing)
  • Nations identity key mode on firmware 0.1.0.15
  • Copilot review
  • fenrir
  • update fenrir to scan wolftpm/spdm

This comment was marked as outdated.

This comment was marked as outdated.

This comment was marked as outdated.

@aidangarske aidangarske requested a review from dgarske February 20, 2026 21:58
@dgarske dgarske assigned dgarske and wolfSSL-Bot and unassigned aidangarske Feb 21, 2026
Copilot AI review requested due to automatic review settings February 24, 2026 16:26

This comment was marked as off-topic.

This comment was marked as outdated.

@dgarske dgarske removed their assignment Feb 24, 2026
Copilot AI review requested due to automatic review settings February 26, 2026 18:20

This comment was marked as outdated.

This comment was marked as resolved.

wolfSSL-Fenrir-bot

This comment was marked as resolved.

Copilot AI review requested due to automatic review settings March 24, 2026 18:13
@aidangarske aidangarske force-pushed the add-full-spdm-support branch from 571388e to 49c7674 Compare March 24, 2026 18:15
@aidangarske aidangarske review requested due to automatic review settings March 24, 2026 18:16
  - Moved spdm/src/*.c src/spdm/*.c (11 source files)
  - Moved spdm/wolfspdm/*.h wolftpm/spdm/*.h (7 public headers)
  - Moved spdm/src/spdm_internal.h src/spdm/spdm_internal.h
  - Moved spdm/test/unit_test.c src/spdm/unit_test.c
  - Moved spdm/README.md src/spdm/README.md
  - Deleted spdm/include.am, created src/spdm/include.am
  - Renamed all #include <wolfspdm/...> #include <wolftpm/spdm/...> across all files
  - Added SPDM headers to wolftpm/include.am (as nobase_include_HEADERS)
  - Updated Makefile.am: include spdm/include.am include src/spdm/include.am
  - Removed -I/spdm from configure.ac and examples/spdm/include.am (no longer needed
@aidangarske aidangarske requested review from Copilot and removed request for Copilot March 24, 2026 23:32
- Renamed spdm_demo to spdm_ctrl: file, binary, internal demo_* functions to ctrl_*, all references in
  include.am, spdm_test.sh, .gitignore, CLAUDE.md, both READMEs
  - README mentions Nations: title updated to Nuvoton NPCT75x and Nations NS350 TPMs, added Nations build section
  - README section header renamed from Demo Commands to Setup/Control Commands
  - README added reset pin control section: documents GPIO reset requirement, Pi-specific example, custom hardware
  design guidance
  - Moved spdm_tcg.c to common build section, no longer conditional on Nuvoton/Nations in src/spdm/include.am
  - Removed redundant wolfSSL options include from spdm_internal.h since tpm2_types.h handles this
  - Added WOLFTPM_SPDM_TCG generic guard as auto-define in spdm_types.h, replaced ~30 occurrences of #if        defined(WOLFSPDM_NUVOTON) || defined(WOLFSPDM_NATIONS) across all files
wolfSSL-Fenrir-bot

This comment was marked as resolved.

This comment was marked as resolved.

This comment was marked as resolved.

… codes from SPDM now return immediately

  instead of falling through to cleartext retry
  - Fixed same SPDM cleartext fallback in TPM2_SendCommandAuth(): same pattern applied
  - Added VdCode validation in wolfTPM2_SPDM_SecuredExchange(): verifies response matches expected TPM2_CMD
  vendor code before accepting payload
  - Upgraded NS350 firmware from 0.1.0.15 to 0.1.0.16 which adds TPM_CMD support under PSK mode (previously returned Vd_InvalidCode)
  - PSK mode: GET_CAPABILITIES and NEGOTIATE_ALGORITHMS are not mandatory, can go directly from GET_VERSION to PSK_EXCHANGE (noted for future optimization)
  - Identity key mode: END_SESSION is mandatory (noted for future addition to test sequence)
  - All 17/17 hardware tests pass on new firmware
  - Fixed SPDM cleartext fallback in TPM2_SendCommand(): positive error codes from SPDM now return immediately instead of falling through to cleartext
  retry
  - Fixed same SPDM cleartext fallback in TPM2_SendCommandAuth(): same pattern applied
  - Added VdCode validation in wolfTPM2_SPDM_SecuredExchange(): verifies response matches expected TPM2_CMD vendor code before accepting payload
  - Enabled auto-connect for Nations: changed guard from WOLFSPDM_NUVOTON to WOLFTPM_SPDM_TCG and replaced wolfTPM2_SpdmConnectNuvoton() with generic
  wolfTPM2_SpdmConnect() so auto-SPDM works for both vendors
  - Added VdCode validation in wolfSPDM_TCG_VendorCmdClear(): verifies response vendor code matches expected value after parsing

This comment was marked as resolved.

  - NATIONS_PSK mode check (tpm2_spdm.c) - Only affects PSK mode which was already broken (raw path instead of VENDOR_DEFINED)
  - END_SESSION (tpm2_wrap.c) - New behavior but only adds an END_SESSION before the existing cleanup. If it fails, cleanup still proceeds.
  - Nations auto-connect (tpm2_wrap.c:279) - Only fires when spdmOnlyDetected is true (TPM locked in SPDM-only mode and TPM2_Startup returned
  TPM_RC_DISABLED). Normal operation never hits this path.
  - VdCode validation (spdm_tcg.c) - This one could theoretically break something if a response VdCode doesn't match. But all callers like
  wolfSPDM_TCG_GetPubKey() already validate VdCode independently (line 316-321), so the existing code was already checking this for specific commands.
  - VCA skip in PSK (spdm_psk.c) - Changes the transcript hash. Needs firmware 0.1.0.16 + NS350 to also skip VCA. Vision confirmed this works.
  - TPM_CMD_Lx defines / comments - No behavioral change.
danielinux
danielinux previously approved these changes Apr 7, 2026

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants